home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / window / _graph_edit.c next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  12.8 KB  |  607 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  _graph_edit.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15. #include <LEDA/graph_edit.h>
  16. #include <LEDA/graph_alg.h>
  17. #include <LEDA/node_matrix.h>
  18.  
  19.  
  20. static window*           Wp;
  21. static GRAPH<point,int>* Gp;
  22. static node_matrix<int>  M;
  23.  
  24.  
  25. static color node_color = green;
  26. static color edge_color = black;
  27. static bool  directed;
  28.  
  29. static int x_min, x_max, y_min, y_max;
  30. static double node_radius;
  31.  
  32. static list<point> cursor_in_edges;
  33. static list<point> cursor_out_edges;
  34.  
  35.  
  36. static void draw_node_cursor(double x, double y)
  37. {
  38.   point q(x,y);
  39.   point p;
  40.   forall(p,cursor_in_edges) Wp->draw_edge(p,q);
  41.   forall(p,cursor_out_edges) Wp->draw_edge(q,p);
  42.   Wp->draw_node(q); 
  43. }
  44.  
  45.  
  46.  
  47. static void draw_node(node v)
  48. { Wp->draw_text_node((*Gp)[v],string("%d",index(v)),node_color); }
  49.  
  50.  
  51.  
  52.  
  53. static void draw_edge(node v, node w)
  54.   // M(v,w) = number of edges from v to w (defines thickness of drawn edge)
  55.  
  56.   if (v == w) return; // still cannot draw self-loops 
  57.  
  58.   if (M(v,w) == 0) return;  // there is no edge (v,w)
  59.  
  60.   int lw_save = Wp->set_line_width(M(v,w));
  61.  
  62.   segment s(Gp->inf(v),Gp->inf(w));
  63.  
  64.   if (directed) 
  65.     if (M(w,v) == 0)
  66.        Wp->draw_edge_arrow(s,edge_color);
  67.     else
  68.        Wp->draw_arc_edge_arrow(s,0.7*s.length(),edge_color);
  69.   else 
  70.     if (M(w,v) == 0)
  71.        Wp->draw_edge(s,edge_color); 
  72.     else
  73.        Wp->draw_arc_edge(s,0.7*s.length(),edge_color);
  74.  
  75.   Wp->set_line_width(lw_save);
  76. }
  77.  
  78.  
  79. static void message(window& W, string s)
  80. { W.del_message();
  81.   W.message(s + "                              ");
  82.  }
  83.  
  84. static edge find_edge(node v, node w)
  85. { edge e = Gp->first_adj_edge(v);
  86.   while (e != nil && target(e) != w) e = Gp->adj_succ(e);
  87.   return e;
  88.  }
  89.  
  90.  
  91. static node V(point p)  // returns node at position p
  92. { node v;
  93.   forall_nodes(v,*Gp)
  94.     if (p.distance(Gp->inf(v)) < node_radius) return v;
  95.   return nil;
  96.  }
  97.  
  98. void init_matrix(const graph& g)
  99. { edge e;
  100.   int n = 100;
  101.   if (g.number_of_nodes() > n) n = 2*g.number_of_nodes();
  102.   M.init(g,n,0);
  103.   forall_edges(e,g) M(source(e),target(e))++;
  104.  }
  105.  
  106.  
  107. static void read_graph(window& W, GRAPH<point,int>& G,string s,bool clear=false)
  108. {
  109.   if (s=="") 
  110.   { message(W,"No file.");
  111.     return;
  112.    }
  113.  
  114.   message(W,string("Reading file %s.",~s));
  115.  
  116.   GRAPH<point,int> X;
  117.   node v;
  118.   node w;
  119.  
  120.   int x = X.read(s);
  121.  
  122.   if (x == 1) 
  123.   { message(W,string("Cannot open file %s.",~s));
  124.     return;
  125.    }
  126.  
  127.   if (x == 2)
  128.   { message(W,"File is not written by graph_edit (random embedding).");
  129.     int max = int(W.xmax())-3;
  130.     int min = 2;
  131.     forall_nodes(v,X)
  132.       X[v] = point(random(min,max), random(min,max));
  133.    }
  134.  
  135.   if (clear) 
  136.   { G.clear(); 
  137.     W.clear(); 
  138.    }
  139.  
  140.   node_array<node> corr(X);
  141.  
  142.   forall_nodes(v,X) 
  143.   { node u = G.new_node(X[v]);
  144.     corr[v] = u;
  145.     draw_node(u);
  146.    }
  147.  
  148.   edge e;
  149.   forall_edges(e,X) 
  150.   { v = corr[source(e)];
  151.     w = corr[target(e)];
  152.     G.new_edge(v,w);
  153.     M(v,w)++;
  154.    }
  155.  
  156.   if (clear) init_matrix(G);
  157.  
  158.   forall_nodes(v,G)
  159.      forall_nodes(w,G) 
  160.         draw_edge(v,w);
  161.  
  162. }
  163.  
  164.  
  165.  
  166. static void save_graph(window& W, GRAPH<point,int>& G,string s)
  167. { if (s=="") 
  168.   { message(W,"Cannot open file.");
  169.     return;
  170.    }
  171.   message(W,string("writing to file %s",~s));
  172.   G.write(s);
  173.  }
  174.  
  175.  
  176. static void generate_graph(GRAPH<point,int>& G)
  177. {
  178.   panel P("GRAPH GENERATORS");;
  179.  
  180.   int n = 10;
  181.   int m = 20;
  182.  
  183.   P.int_item("# nodes", n,0,500);
  184.   P.int_item("# edges", m,0,500);
  185.  
  186.   P.button("random");
  187.   P.button("complete");
  188.   P.button("bi_random");
  189.   P.button("bi_complete");
  190.   P.button("planar");
  191.   P.button("grid");
  192.   P.button("triang");
  193.   P.button("exit");
  194.  
  195.   list<node> A,B;
  196.   node v;
  197.  
  198.   G.clear();
  199.  
  200.   node_array<double> xcoord(G);
  201.   node_array<double> ycoord(G);
  202.  
  203.   double w = x_max - x_min;
  204.   double h = y_max - y_min;
  205.  
  206.   double R  = (x_max-x_min)/2.5;
  207.   double x0 = (x_max-x_min)/2;
  208.   double y0 = (y_max-y_min)/2;
  209.  
  210.   int i = P.open(*Wp);
  211.  
  212.   switch(i)
  213.   {
  214.     case 0: random_graph(G,n,m);
  215.             break;
  216.     case 1: complete_graph(G,n);
  217.             break;
  218.  
  219.     case 2: random_bigraph(G,n,n,m,A,B);
  220.             break;
  221.  
  222.     case 3: complete_bigraph(G,n,n,A,B);
  223.             break;
  224.  
  225.     case 4: { random_planar_graph(G,xcoord,ycoord,n);
  226.               node v;
  227.               forall_nodes(v,G)  
  228.                  G[v] = point(x_min + w*xcoord[v], y_min + h*ycoord[v]);
  229.               break;
  230.              }
  231.  
  232.     case 5: { grid_graph(G,xcoord,ycoord,n);
  233.               node v;
  234.               forall_nodes(v,G)  
  235.                  G[v] = point(x_min + w*xcoord[v], y_min + h*ycoord[v]);
  236.               break;
  237.              }
  238.  
  239.     case 6: { triangulated_planar_graph(G,xcoord,ycoord,n);
  240.               node v;
  241.               forall_nodes(v,G)  
  242.                  G[v] = point(x_min + w*xcoord[v], y_min + h*ycoord[v]);
  243.               break;
  244.              }
  245.    }
  246.  
  247.    if ( i==2 || i==3 )
  248.    { double dy = (y_max-y_min)/(n+1);
  249.      double y = y_min + dy;
  250.      forall(v,A) 
  251.      { G[v] = point(x_min + (x_max-x_min)/4,y);
  252.        y += dy;
  253.       }
  254.      y = y_min + dy;
  255.      forall(v,B) 
  256.      { G[v] = point(x_max - (x_max-x_min)/4,y);
  257.        y += dy;
  258.       }
  259.      }
  260.  
  261.    if (i==0 || i==1) // circular embedding 
  262.    { double R  = (x_max-x_min)/2.5;
  263.      double x0 = (x_max-x_min)/2;
  264.      double y0 = (y_max-y_min)/2;
  265.      point  M(x0,y0);
  266.      double alpha = 0;
  267.      double step  = 6.2832/n;
  268.      forall_nodes(v,G)  
  269.      { G[v] = M.translate(alpha,R);
  270.        alpha+=step;
  271.       }
  272.     }
  273.  
  274.   init_matrix(G);
  275. }
  276.  
  277.  
  278. static void redraw_func()
  279. { Wp->set_mode(src_mode);
  280.   node v;
  281.   forall_nodes(v,*Gp) 
  282.   { draw_node(v);
  283.     node w;
  284.     forall_nodes(w,*Gp) draw_edge(v,w);
  285.    }
  286.   Wp->set_mode(xor_mode);
  287.  }
  288.  
  289.  
  290.  
  291. static void window_init(window& W, GRAPH<point,int>& G)
  292.   W.init(x_min,x_max,y_min,0);
  293.  
  294.   if (W.mono()) node_color = white;
  295.  
  296.   W.set_redraw(redraw_func);
  297.   W.set_mode(src_mode);
  298.  
  299.   node_radius = W.get_node_width()/W.scale();
  300.  
  301.   node v;
  302.   forall_nodes(v,G) 
  303.   { draw_node(v);
  304.     node w;
  305.     forall_nodes(w,G) draw_edge(v,w);
  306.    }
  307.  
  308.   W.set_mode(xor_mode);
  309.  
  310. }
  311.  
  312.  
  313.  
  314. void graph_edit(window& W, GRAPH<point,int>& G, bool dir, bool redraw)
  315. {
  316.   double x,y;
  317.   point  p,q;
  318.   int    key;
  319.  
  320.   Wp = &W;
  321.   Gp = &G;
  322.  
  323.   init_matrix(G);
  324.  
  325.   x_min = (int)W.xmin();
  326.   x_max = (int)W.xmax();
  327.   y_min = (int)W.ymin();
  328.   y_max = (int)W.ymax();
  329.  
  330.   directed = dir;
  331.   node_radius = W.get_node_width()/W.scale();
  332.  
  333.  
  334.   string filename = "graph.ggg";
  335.  
  336.   panel main_panel("GRAPH EDIT MAIN PANEL");
  337.   main_panel.text_item("");
  338.   main_panel.text_item("graph_edit: A Graph Editor For LEDA Graphs.");
  339.   main_panel.text_item("");
  340.   main_panel.string_item("file:",filename);
  341.   main_panel.button("load");
  342.   main_panel.button("read");
  343.   main_panel.button("save");
  344.   main_panel.button("redraw");
  345.   main_panel.button("clear");
  346.   main_panel.button("gen");
  347.   main_panel.button("zoom");
  348.   main_panel.button("params");
  349.   main_panel.button("help");
  350.   main_panel.button("done");
  351.  
  352.  
  353.  
  354.   panel help_panel("GRAPH EDIT OPERATIONS");
  355.   help_panel.text_item("                                             ");
  356.   help_panel.text_item("          left button        middle button    ");
  357.   help_panel.text_item("                                             ");
  358.   help_panel.text_item("        insert/move node      insert edge     ");
  359.   help_panel.text_item("(shift)   delete node         delete edge     ");
  360.   help_panel.text_item("                                             ");
  361.   help_panel.button("continue");
  362.  
  363.  
  364.   panel init_panel("SETTINGS");
  365.   init_panel.int_item("x_min",x_min);
  366.   init_panel.int_item("x_max",x_max);
  367.   init_panel.int_item("y_min",y_min);
  368.   init_panel.color_item("node color",node_color);
  369.   init_panel.color_item("edge color",edge_color);
  370.   init_panel.button("continue");
  371.  
  372.  
  373.  
  374.   main_panel.display(W,0,0);
  375.  
  376.   drawing_mode save = W.set_mode(xor_mode);
  377.  
  378.  
  379.   if (redraw) window_init(W,G);
  380.  
  381.   bool done = false;
  382.  
  383.   LEDA_WINDOW* wp;
  384.  
  385.   while ( ! done )
  386.   {
  387.     read_mouse(wp,x,y);
  388.  
  389.     if (wp == &W || wp == &main_panel) put_back_event();
  390.  
  391.  
  392.     if (wp == &main_panel)
  393.     { int k = main_panel.read();
  394.  
  395.       switch (k) { 
  396.  
  397.       case 0 : // load 
  398.                read_graph(W,G,filename,true);
  399.                break;
  400.  
  401.       case 1 : // read
  402.                read_graph(W,G,filename,false);
  403.                break;
  404.   
  405.       case 2 : // save
  406.                save_graph(W,G,filename);
  407.                break;
  408.  
  409.       case 3:  // redraw
  410.                window_init(W,G);
  411.                break;
  412.  
  413.       case 4:  // clear
  414.                W.clear();
  415.                G.clear();
  416.                init_matrix(G);
  417.                break;
  418.  
  419.       case 5:  // generate
  420.                generate_graph(G);
  421.                window_init(W,G);
  422.                break;
  423.  
  424.  
  425.       case 6:  // zoom
  426.                W.acknowledge("Sorry, zoom not implemented.");
  427.                break;
  428.  
  429.  
  430.       case 7:  // settings
  431.                init_panel.open();
  432.                window_init(W,G);
  433.                break;
  434.  
  435.       case 8:  // help
  436.                help_panel.open();
  437.                break;
  438.   
  439.  
  440.       case 9: done = true;
  441.               break;
  442.      }
  443.  
  444.      continue;
  445.     }
  446.  
  447.  
  448.      key = W.read_mouse(x,y);
  449.  
  450.      W.del_message();
  451.  
  452.      p = point(x,y);
  453.  
  454.      switch(key) {
  455.  
  456.      case 1:  { 
  457.                 node v = V(p);
  458.  
  459.                 if (v == nil)        // new node
  460.                 { v  = G.new_node(p);
  461.                   draw_node(v);
  462.                  }
  463.                 else                    // move node
  464.                 { 
  465.                   draw_node(v);
  466.  
  467.                   cursor_in_edges.clear();
  468.                   cursor_out_edges.clear();
  469.                   edge e;
  470.                   forall_in_edges(e,v)  
  471.                   { draw_edge(source(e),v);
  472.                     cursor_in_edges.append(G[source(e)]); 
  473.                    }
  474.                   forall_out_edges(e,v)
  475.                   { draw_edge(v,target(e));
  476.                     cursor_out_edges.append(G[target(e)]); 
  477.                    }
  478.                   W.read_mouse_action(draw_node_cursor,x,y);
  479.  
  480.                   forall_in_edges(e,v)  draw_edge(source(e),v);
  481.                   forall_out_edges(e,v) draw_edge(v,target(e));
  482.  
  483.  
  484.  
  485.                   point q(x,y);           // new position
  486.  
  487.                   if (V(q) != nil)        // position not free
  488.                   { draw_node(v);
  489.                     break;
  490.                    }
  491.  
  492.                   node w;
  493.  
  494.                   forall_nodes(w,G)    // remove adjacent edges
  495.                   { draw_edge(v,w);
  496.                     draw_edge(w,v);
  497.                    }
  498.  
  499.                   G[v] = q;
  500.                   draw_node(v);
  501.  
  502.                   forall_nodes(w,G)    // reinsert adjacent edges
  503.                   { draw_edge(v,w);
  504.                     draw_edge(w,v);
  505.                    }
  506.  
  507.                  }
  508.                 break;
  509.                }
  510.  
  511.  
  512.      case 2:  { // new edge
  513.                 
  514.                 node v = V(p);   // start node
  515.  
  516.                 if (v != nil)            
  517.                 { p = G[v];
  518.  
  519.                   W.draw_filled_node(p);   // highlight start node
  520.  
  521.                   W.read_mouse_seg(p.xcoord(),p.ycoord(),x,y);
  522.  
  523.                   point q(x,y);
  524.                   node w = V(q);
  525.  
  526.                   if (w == nil)      // no hit: create a new node w at q
  527.                   { w  = G.new_node(q);
  528.                     draw_node(w);
  529.                    }
  530.  
  531.                   draw_edge(v,w);   // delete possible edge drawings
  532.                   draw_edge(w,v);
  533.  
  534.                   G.new_edge(v,w);  // insert new edge
  535.                   M(v,w)++;
  536.  
  537.                   draw_edge(w,v);   // reinsert edge drawings
  538.                   draw_edge(v,w);
  539.  
  540.                   W.draw_filled_node(p);  // un-highlight start node
  541.                  }
  542.  
  543.                 break;
  544.                }
  545.  
  546.  
  547.  
  548.      // Shift + mouse key
  549.  
  550.  
  551.      case -1: { // delete node
  552.  
  553.                 node v = V(p);
  554.  
  555.                 if (v != nil) 
  556.                 { node w; 
  557.                   forall_nodes(w,G)    // remove adjacent edges
  558.                   { draw_edge(v,w);
  559.                     draw_edge(w,v);
  560.                     M(v,w) = M(w,v) = 0;
  561.                    }
  562.  
  563.                   draw_node(v);
  564.  
  565.                   G.del_node(v);
  566.                  }
  567.  
  568.                 }
  569.  
  570.      case -2: { // delete edge
  571.  
  572.                 node v = V(p);
  573.  
  574.                 if (v != nil) 
  575.                 { p = G[v];
  576.                   W.read_mouse_seg(p.xcoord(),p.ycoord(),x,y);
  577.                   q = point(x,y);
  578.                   node w = V(q);
  579.                   if (w != nil) 
  580.                   { edge e = find_edge(v,w);
  581.                     if (e != nil)
  582.                     { draw_edge(v,w);
  583.                       draw_edge(w,v);
  584.                       G.del_edge(e);
  585.                       M(v,w)--;
  586.                       draw_edge(w,v);
  587.                       draw_edge(v,w);
  588.                      }
  589.                    }
  590.                  }
  591.                 break;
  592.                }
  593.  
  594.  
  595.     } // switch
  596.  
  597.   } // for(;;)
  598.  
  599.   W.reset_frame_label();
  600.   W.set_mode(save);
  601.   W.set_redraw(nil);
  602. }
  603.  
  604.